#include <ut/eventloop.h>
#include <ut/logstream.h>
#include <ut/channel.h>
#include <ut/thread.h>

#include <sys/eventfd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

using namespace ut;

void read_test(int efd)
{
    uint64_t u;
    ssize_t s;
    s = read(efd, &u, sizeof(uint64_t));
    UT_DEBUG << "read:" << u;
}

void write_test(int efd)
{
    uint64_t u;
    ssize_t s;
    while (true) {
        u = 100;
        /* strtoull() allows various bases */
        s = write(efd, &u, sizeof(uint64_t));
        UT_DEBUG << "write:" << u;
        sleep(2);
    }
}

void unix_socket_server()
{
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_un server_address;
    struct sockaddr_un client_address;
    int i, byte;
    char ch_send, recv_buf[128];

    unlink("server_socket"); //解除原有server_socket对象链接
    server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); //创建socket，指定通信协议为AF_UNIX,数据方式SOCK_STREAM
    //配置server_address
    server_address.sun_family = AF_UNIX;
    strcpy(server_address.sun_path, "server_socket");
    server_len = sizeof(server_address);

    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

    listen(server_sockfd, 5);

    printf("server waiting for  client connect\n");
    client_len = sizeof(client_address);
    // accept函数接收客户端求情，存储客户端地址信息、客户端地址大小
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, (socklen_t *)&client_len);
    printf("the server wait form client data\n");

    for (i = 0, ch_send = '1'; i < 5; i++, ch_send++) {
        //从client_sockfd读取客户端发来的消息
        if ((byte = read(client_sockfd, recv_buf, sizeof(recv_buf))) == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        printf("the massage receiver from client is: %s\n", recv_buf);
        sleep(1);
        //向客户端发送消息
        if ((byte = write(client_sockfd, &ch_send, 1)) == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }
    }
    close(client_sockfd);
    unlink("server socket");
}
void unix_socket_client()
{
    int sockfd;
    int len;
    struct sockaddr_un address;
    int result;
    int i, byte;
    char send_buf[128], ch_recv;

    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) //创建socket，指定通信协议为AF_UNIX,数据方式SOCK_STREAM
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    //配置server_address
    address.sun_family = AF_UNIX;
    strcpy(address.sun_path, "server_socket");
    len = sizeof(address);

    result = connect(sockfd, (struct sockaddr *)&address, len);
    UT_DEBUG << "result:" << result;
    if (result == -1) {
        printf("ensure the server is up\n");
        perror("connect");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < 5; i++) {
        sprintf(send_buf, "client massage %d", i); //用sprintf事先把消息写到send_buf
        if ((byte = write(sockfd, send_buf, sizeof(send_buf))) == -1) {
            perror("write");
            exit(EXIT_FAILURE);
        }
        if ((byte = read(sockfd, &ch_recv, 1)) == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        printf("receive from server data is: %c\n", ch_recv);
    }
    close(sockfd);
}
int main(int argc, char **argv)
{
    LogStream::category("test_eventloop");
    EventLoop a;

    int efd = eventfd(0, 0);
    Channel channel(&a, efd);
    channel.poll_return(std::bind(read_test, efd));
    channel.enable_reading();
    Thread thread(std::bind(write_test, efd));
    thread.start();

    Thread server(unix_socket_server);
    server.start();
    sleep(1);
    Thread client(unix_socket_client);
    client.start();

    a.loop();
    return 0;
}